package com.hw.common.utils;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.hw.common.framework.exception.BaseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import java.util.Map;

/**
 * 3DES加密
 */
@SuppressWarnings("restriction")
public class ThreeDes {
   private final static Logger LOGGER = LoggerFactory.getLogger(ThreeDes.class);
   
   /***
    * 需要使用THREE_DES_APP_KEY加密，APP使用THREE_DES_APP_KEY解密该密钥，然后解密网关业务数据
    */
   private static final String THREE_DES_SERVICE_KEY = "1qazxsw23edcvfr45tgbnhy6";
   
   /***
    * APP客户端和服务约定好的密钥，使用该密钥加密网关密钥
    */
   private static final String THREE_DES_APP_KEY = "123456789012345678901234";
   
   /**
    * <pre>
    * 功能：获取使用versionKey加密后的服务密钥
    * 创建人：JokenWang
    * 创建时间：2015年2月27日 下午2:08:48
    * </pre>
    *
    * @return 使用versionKey加密后的服务密钥
    * @version 1.0.0
    */
   public static String getBaseKey() {
      return encrypt(THREE_DES_SERVICE_KEY, THREE_DES_APP_KEY);
   }
   
   /***
    * <pre>
    * 功能：获取网关加密的密钥
    * 创建人：JokenWang
    * 创建时间：2015年2月27日 下午2:12:15
    * </pre>
    *
    * @return 网关加密的密钥
    * @version 1.0.0
    */
   public static String getServiceDataEncryptKey() {
      return THREE_DES_SERVICE_KEY;
   }
   
   /**
    * <pre>
    * 功能：加密
    * 创建人：JokenWang
    * 创建时间：2015年1月29日 下午2:59:00
    * </pre>
    *
    * @param src 待加密的字符串
    * @param key 加密使用的密钥
    * @return 加密后的密文字符串
    * @version 1.0.0
    */
   public static String encrypt(String src)// 3DESECB加密,key必须是长度大于等于 3*8 = 24 位
   {
      byte[] b = null;
      try {
         // 通过base64, 加密
         BASE64Encoder encoder = new BASE64Encoder();
         src = encoder.encode(src.getBytes("UTF-8"));
         
         DESedeKeySpec dks = new DESedeKeySpec(THREE_DES_SERVICE_KEY.getBytes("UTF-8"));
         SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
         SecretKey securekey = keyFactory.generateSecret(dks);
         
         Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
         cipher.init(Cipher.ENCRYPT_MODE, securekey);
         b = cipher.doFinal(src.getBytes("UTF-8"));
      } catch (Exception e) {
         LOGGER.error("加密异常：{}", BaseException.stackTraceToString(e));
      }
      
      BASE64Encoder encoder = new BASE64Encoder();
      return encoder.encode(b).replaceAll("\r|\n", "");
   }
   
   /**
    * <pre>
    * 功能：加密
    * 创建人：JokenWang
    * 创建时间：2015年1月29日 下午2:59:00
    * </pre>
    *
    * @param src 待加密的字符串
    * @param key 加密使用的密钥
    * @return 加密后的密文字符串
    * @version 1.0.0
    */
   public static String encrypt(String src, String key)// 3DESECB加密,key必须是长度大于等于 3*8 = 24 位
   {
      byte[] b = null;
      try {
         // 通过base64, 加密
         BASE64Encoder encoder = new BASE64Encoder();
         src = encoder.encode(src.getBytes("UTF-8"));
         
         DESedeKeySpec dks = new DESedeKeySpec(key.getBytes("UTF-8"));
         SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
         SecretKey securekey = keyFactory.generateSecret(dks);
         
         Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
         cipher.init(Cipher.ENCRYPT_MODE, securekey);
         b = cipher.doFinal(src.getBytes("UTF-8"));
      } catch (Exception e) {
         LOGGER.error("加密异常：{}", BaseException.stackTraceToString(e));
      }
      
      BASE64Encoder encoder = new BASE64Encoder();
      return encoder.encode(b).replaceAll("\r|\n", "");
   }
   
   /**
    * <pre>
    * 功能：加密
    * 创建人：JokenWang
    * 创建时间：2015年1月29日 下午3:00:39
    * </pre>
    *
    * @param map 待加密的键值对@param key
    * @param key 加密使用的密钥
    * @return 加密后的密文字符串
    * @version 1.0.0
    */
   public static String encrypt(Map<?, ?> map, String key) {
      ObjectMapper mapper = new ObjectMapper();
      byte[] b = null;
      try {
         String src = mapper.writeValueAsString(map);
         // 通过base64, 加密
         BASE64Encoder encoder = new BASE64Encoder();
         src = encoder.encode(src.getBytes("UTF-8"));
         
         DESedeKeySpec dks = new DESedeKeySpec(key.getBytes("UTF-8"));
         SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
         SecretKey securekey = keyFactory.generateSecret(dks);
         
         Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
         cipher.init(Cipher.ENCRYPT_MODE, securekey);
         b = cipher.doFinal(src.getBytes("UTF-8"));
      } catch (Exception e) {
         LOGGER.error("加密异常：{}", BaseException.stackTraceToString(e));
      }
      
      BASE64Encoder encoder = new BASE64Encoder();
      return encoder.encode(b).replaceAll("\r|\n", "");
   }
   
   /**
    * <pre>
    * 功能：加密
    * 创建人：JokenWang
    * 创建时间：2015年1月29日 下午3:00:39
    * </pre>
    *
    * @param map 待加密的键值对@param key
    * @param key 加密使用的密钥
    * @return 加密后的密文字符串
    * @version 1.0.0
    */
   public static String encrypt(Map<?, ?> map) {
      ObjectMapper mapper = new ObjectMapper();
      byte[] b = null;
      try {
         String src = mapper.writeValueAsString(map);
         // 通过base64, 加密
         BASE64Encoder encoder = new BASE64Encoder();
         src = encoder.encode(src.getBytes("UTF-8"));
         
         DESedeKeySpec dks = new DESedeKeySpec(THREE_DES_SERVICE_KEY.getBytes("UTF-8"));
         SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
         SecretKey securekey = keyFactory.generateSecret(dks);
         
         Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
         cipher.init(Cipher.ENCRYPT_MODE, securekey);
         b = cipher.doFinal(src.getBytes("UTF-8"));
      } catch (Exception e) {
         LOGGER.error("加密异常：{}", BaseException.stackTraceToString(e));
      }
      
      BASE64Encoder encoder = new BASE64Encoder();
      return encoder.encode(b).replaceAll("\r|\n", "");
   }
   
   /***
    * <pre>
    * 功能：解密
    * 创建人：JokenWang
    * 创建时间：2015年1月29日 下午3:02:36
    * </pre>
    *
    * @param src
    *            待解密的密文字符串
    * @param key
    *            加密使用的密钥
    * @return 解密后的字符串
    * @version 1.0.0
    */
   public static String decrypt(String src, String key)// 3DESECB解密,key必须是长度大于等于 3*8 = 24 位
   {
      if (src == null) {
         return null;
      }
      byte[] retByte = null;
      try {
         // --通过BASE64,将字符串转成byte数组
         BASE64Decoder decoder = new BASE64Decoder();
         byte[] bytesrc;
         
         bytesrc = decoder.decodeBuffer(src);
         
         // --解密的KEY
         DESedeKeySpec dks = new DESedeKeySpec(key.getBytes("UTF-8"));
         SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
         SecretKey securekey = keyFactory.generateSecret(dks);
         
         // --CHIPHER对象解密
         Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
         cipher.init(Cipher.DECRYPT_MODE, securekey);
         retByte = cipher.doFinal(bytesrc);
         
         // 通过BASE64,再次加密
         retByte = decoder.decodeBuffer(new String(retByte, "UTF-8"));
         return new String(retByte, "UTF-8");
      } catch (Exception e) {
         LOGGER.error("解密异常：{}", BaseException.stackTraceToString(e));
         
         return null;
      }
   }
   
   /***
    * <pre>
    * 功能：解密
    * 创建人：JokenWang
    * 创建时间：2015年1月29日 下午3:02:36
    * </pre>
    *
    * @param src
    *            待解密的密文字符串
    * @param key
    *            加密使用的密钥
    * @return 解密后的字符串
    * @version 1.0.0
    */
   public static String decrypt(String src)// 3DESECB解密,key必须是长度大于等于 3*8 = 24 位
   {
      if (src == null) {
         return null;
      }
      byte[] retByte = null;
      try {
         // --通过BASE64,将字符串转成byte数组
         BASE64Decoder decoder = new BASE64Decoder();
         byte[] bytesrc;
         
         bytesrc = decoder.decodeBuffer(src);
         
         // --解密的KEY
         DESedeKeySpec dks = new DESedeKeySpec(THREE_DES_SERVICE_KEY.getBytes("UTF-8"));
         SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
         SecretKey securekey = keyFactory.generateSecret(dks);
         
         // --CHIPHER对象解密
         Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
         cipher.init(Cipher.DECRYPT_MODE, securekey);
         retByte = cipher.doFinal(bytesrc);
         
         // 通过BASE64,再次加密
         retByte = decoder.decodeBuffer(new String(retByte, "UTF-8"));
         return new String(retByte, "UTF-8");
      } catch (Exception e) {
         LOGGER.error("解密异常：{}", BaseException.stackTraceToString(e));
         
         return null;
      }
   }
}
